// 卡片子组件：处理卡片渲染、手势、过渡与底部操作区
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useI18n } from '@/utils/in18';
import { request } from '@/utils/request';
import { hasStoredToken } from '@/utils/auth';
import likeIcon from '@/assets/home/like.png'//喜欢
import { openLoginModal } from '@/componets/loginModel';
import dislikeIcon from '@/assets/home/dislike.png'//不喜欢
import select_likeIcon from '@/assets/home/select_like.png'//选择喜欢
import select_dislikeIcon from '@/assets/home/select_dislike.png'//选择不喜欢
import backIcon from '@/assets/home/back.png' //上一张图片

// 性能优化：throttle 函数实现
const throttle = <T extends (...args: any[]) => any>(func: T, delay: number): T => {
    let timeoutId: NodeJS.Timeout | null = null;
    let lastExecTime = 0;
    
    return ((...args: Parameters<T>) => {
        const currentTime = Date.now();
        
        if (currentTime - lastExecTime > delay) {
            func(...args);
            lastExecTime = currentTime;
        } else {
            if (timeoutId) clearTimeout(timeoutId);
            timeoutId = setTimeout(() => {
                func(...args);
                lastExecTime = Date.now();
            }, delay - (currentTime - lastExecTime));
        }
    }) as T;
};

export type CardItem = {
    id: number;
    title: string;
    desc?: string;
    src?: string;
    raw?: any;
};

type CardsProps = {
    onCardClick?: (card: CardItem) => void; // 点击卡片时调用
    // 下沉数据获取：不再从父组件传 items/onNeedMore/initialIndex
    // 仅接收筛选条件，内部自行请求与分页
    filters?: { keyword?: string; race?: string; category?: string; origin?: string } | null;
    prefetchThreshold?: number; // 触发内部预取的剩余阈值（默认 6）
    windowSize?: number; // 渲染窗口大小，仅渲染顶部若干张以优化性能（默认 4）
};

const Cards: React.FC<CardsProps> = React.memo(({ onCardClick, filters, prefetchThreshold, windowSize }) => {
    const { t, locale } = useI18n(); //语言国际化
    // 顶部索引与拖拽状态
    const [topIndex, setTopIndex] = useState<number>(0);
    // 内部数据与加载状态
    const [fetchedItems, setFetchedItems] = useState<any[]>([]);
    const [page, setPage] = useState<number>(1);
    const [isLoading, setIsLoading] = useState<boolean>(false);
    const loadingRef = useRef<boolean>(false);
    const noMoreRef = useRef<boolean>(false);
    const lastRequestTimeRef = useRef<number>(0);
    const requestQueueRef = useRef<Set<string>>(new Set());
    const isRestoringRef = useRef<boolean>(false);
    const skipFirstPrefetchAfterRestoreRef = useRef<boolean>(false);
    const lastFiltersSigRef = useRef<string | null>(null);

    // 本地存储键
    const STORAGE_KEY = 'home_cards_component_state';

    // 将后端原始数据映射为卡片渲染所需的结构 - 使用useMemo优化性能
    const cards = useMemo<CardItem[]>(() => {
        const list = Array.isArray(fetchedItems) ? fetchedItems : [];
        return list.map((it: any, idx: number) => {
            // 这里优先使用后端返回的 id 字段，若不存在再退回到数组索引（保守做法）
            const realId = typeof it?.id === 'number' ? it.id : idx;
            let url = '';
            try { url = String(it?.image_url ?? '').replace(/\s+/g, ' ').trim(); } catch { }
            const title = String(it?.name ?? '');
            return {
                id: realId,
                title,
                desc: '',
                src: url,
                raw: it,
            };
        });
    }, [fetchedItems]);

    // 滑动相关状态变量
    const [isAnimating, setIsAnimating] = useState<boolean>(false); // 动画状态
    const [animateDirection, setAnimateDirection] = useState<"left" | "right" | null>(null); // 动画方向
    const [deltaX, setDeltaX] = useState<number>(0); // X轴偏移量
    const [deltaY, setDeltaY] = useState<number>(0); // Y轴偏移量，用于更精确的手势判断
    const [isDragging, setIsDragging] = useState<boolean>(false); // 拖拽状态
    const [touchStartX, setTouchStartX] = useState<number>(0); // 触摸开始位置
    const [touchStartY, setTouchStartY] = useState<number>(0); // 触摸开始Y位置
    const [isSwipeActive, setIsSwipeActive] = useState<boolean>(false); // 滑动激活状态，用于禁用页面滚动
    const threshold = 80; // 滑动阈值，优化为更合理的值
    const globalProgress = Math.abs(deltaX) / threshold; // 全局进度，基于滑动距离计算
    const [loadedIds, setLoadedIds] = useState<Set<number>>(new Set()); // 图片加载状态映射，用于骨架屏
    const imgRefs = useRef<Record<number, HTMLImageElement | null>>({});
    const [showGuide, setShowGuide] = useState<boolean>(false); // 是否显示滑动指引
    
    // 性能优化相关
    const animationFrameRef = useRef<number | null>(null);
    const lastUpdateTimeRef = useRef<number>(0);
    const velocityRef = useRef<number>(0);
    const lastPositionRef = useRef<number>(0);

    // 登录/游客交互限制
    const GUEST_COUNT_KEY = 'guestActionCount';
    const GUEST_LIKED_KEY = 'guestLikedIds';
    const MAX_GUEST_ACTIONS = 6;
    // 按钮选中状态：独立控制，不受滑动动画影响
    const [buttonLeftSelected, setButtonLeftSelected] = useState<boolean>(false);
    const [buttonRightSelected, setButtonRightSelected] = useState<boolean>(false);
    const containerClass = "relative h-full inline-block mx-[auto] w-[100%] max-w-[1200px]";// 容器占满父容器高度与宽度
    // 判断是否登录
    const isLoggedIn = React.useCallback((): boolean => {
        try {
            const token = localStorage.getItem('token');
            return !!token;
        } catch (error) {
            console.error('检查登录状态失败:', error);
            return false;
        }
    }, []);

    // 获取游客操作次数
    const getGuestActionCount = React.useCallback((): number => {
        try {
            const count = localStorage.getItem(GUEST_COUNT_KEY);
            return count ? parseInt(count, 10) : 0;
        } catch (error) {
            console.error('获取游客操作次数失败:', error);
            return 0;
        }
    }, []);

    // 增加游客操作次数
    const incrementGuestActionCount = React.useCallback((): void => {
        try {
            const currentCount = getGuestActionCount();
            localStorage.setItem(GUEST_COUNT_KEY, (currentCount + 1).toString());
        } catch (error) {
            console.error('增加游客操作次数失败:', error);
        }
    }, [getGuestActionCount]);

    // 检查游客是否可以继续操作
    const canGuestContinue = React.useCallback((): boolean => {
        if (isLoggedIn()) return true;
        return getGuestActionCount() < MAX_GUEST_ACTIONS;
    }, [isLoggedIn, getGuestActionCount]);

    // 获取游客已点赞的ID列表
    const getGuestLikedIds = React.useCallback((): Set<number> => {
        try {
            const likedIds = localStorage.getItem(GUEST_LIKED_KEY);
            return likedIds ? new Set(JSON.parse(likedIds)) : new Set();
        } catch (error) {
            console.error('获取游客点赞记录失败:', error);
            return new Set();
        }
    }, []);

    // 添加游客点赞ID
    const addGuestLikedId = React.useCallback((id: number): void => {
        try {
            const likedIds = getGuestLikedIds();
            likedIds.add(id);
            localStorage.setItem(GUEST_LIKED_KEY, JSON.stringify(Array.from(likedIds)));
        } catch (error) {
            console.error('添加游客点赞记录失败:', error);
        }
    }, [getGuestLikedIds]);

    // 检查是否已点赞
    const isAlreadyLiked = React.useCallback((id: number): boolean => {
        if (isLoggedIn()) {
            // 登录用户的点赞状态应该从服务器获取
            return false; // 这里应该根据实际的API返回值来判断
        } else {
            return getGuestLikedIds().has(id);
        }
    }, [isLoggedIn, getGuestLikedIds]);

    // 删除重复的函数定义，使用上面已定义的useCallback版本

    // 提交游客操作
    const commitGuestAction = useCallback((direction: "left" | "right", likedId?: number) => {
        if (isLoggedIn()) return;
        
        // 使用正确的函数名
        incrementGuestActionCount();
        
        if (direction === 'right' && typeof likedId === 'number') {
            addGuestLikedId(likedId);
        }
    }, [isLoggedIn, incrementGuestActionCount, addGuestLikedId]);

    // 已登录点赞：右滑或点击喜欢即上报
    const likeTemplate = React.useCallback((templateId: number | undefined) => {
        try {
            const idToSend = (typeof templateId === 'number' && Number.isFinite(templateId)) ? templateId : undefined;
            if (!idToSend) return;
            // 读取 user_token；存在则发起请求，不存在则记录为游客喜欢
            let authToken: string | undefined;
            try {
                const raw = localStorage.getItem('userData');
                const parsed = raw ? JSON.parse(raw as string) : null;
                if (parsed && parsed.user_token) authToken = `${parsed.user_token}`;
            } catch { }
            if (!authToken) {
                // 无 token：按游客逻辑记录喜欢的 id
                addGuestLikedId(idToSend);
                return;
            }
            const config = { headers: { Authorization: authToken } };
            request.post('/api/template/likeTemplateRoute', { template_id: [idToSend] }, config).catch(() => { /* ignore */ });
        } catch {
            // ignore
        }
    }, []);

    // 获取当前显示的卡片（直接使用数组索引，不再使用随机索引）- 使用useCallback优化性能
    const getCurrentCard = useCallback((index: number): CardItem | undefined => {
        if (index >= cards.length) return undefined;
        return cards[index] || undefined;
    }, [cards]);

    // 加载缓存：在首次挂载时尝试从 sessionStorage 恢复
    useEffect(() => {
        try {
            const raw = sessionStorage.getItem(STORAGE_KEY);
            if (raw) {
                const saved = JSON.parse(raw as string);
                const savedSig = String(saved?.filtersSignature || '');
                const currentSig = JSON.stringify(filters || {});
                const sameSig = savedSig === currentSig;
                const samePath = String(saved?.path || '') === (typeof window !== 'undefined' ? window.location.pathname : '');
                if (sameSig && samePath && Array.isArray(saved?.items)) {
                    isRestoringRef.current = true;
                    skipFirstPrefetchAfterRestoreRef.current = true;
                    setFetchedItems(saved.items as any[]);
                    setPage(typeof saved.page === 'number' ? saved.page : 1);
                    const nextTop = Math.max(0, Math.min(typeof saved.topIndex === 'number' ? saved.topIndex : 0, (saved.items as any[]).length));
                    setTopIndex(nextTop);
                    if (saved.noMore === true) noMoreRef.current = true;
                    lastFiltersSigRef.current = currentSig; // 防止后续 filters effect 触发刷新
                    // 结束恢复标记（允许后续正常逻辑运行）
                    isRestoringRef.current = false;
                    return; // 使用缓存完成初始化
                }
            }
        } catch { }
        // 无有效缓存，则触发首次拉取
        lastFiltersSigRef.current = JSON.stringify(filters || {});
        noMoreRef.current = false;
        setFetchedItems([]);
        setPage(1);
        setTopIndex(0);
        fetchAndAppendPage(1, 'replace');
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    // 筛选变化：若签名变更，则重置并拉取第一页；若与缓存一致则不动
    const fetchAndAppendPage = useCallback(async (targetPage: number, mode: 'replace' | 'append' = 'replace') => {
        const effectiveFilters = filters || null;
        const requestKey = `${targetPage}-${JSON.stringify(effectiveFilters || {})}`;
        const now = Date.now();

        if (!requestQueueRef.current.has(requestKey)) {
            // 基础节流/去重
            if (loadingRef.current) return null;
            if (noMoreRef.current && mode === 'append') return null;
            if (now - lastRequestTimeRef.current < 400) return null;
        } else {
            return null;
        }

        loadingRef.current = true;
        requestQueueRef.current.add(requestKey);
        setIsLoading((prev) => (mode === 'replace' ? true : prev));
        lastRequestTimeRef.current = now;

        try {
            const payload: any = {
                search: effectiveFilters?.keyword?.trim?.() || '',
                category: effectiveFilters?.category || '',
                race: effectiveFilters?.race || '',
                origin: effectiveFilters?.origin || '',
                name: '',
                sort: 'smart',
                page: targetPage,
                page_size: 12,
                language: locale || 'en',
                information: ['image_url', 'name', 'id', 'role_prompt'],
            };

            // 添加用户ID（如果已登录）
            if (hasStoredToken()) {
                try {
                    const raw = localStorage.getItem('userData');
                    const parsed = raw ? JSON.parse(raw as string) : null;
                    const user_id = parsed?.id;
                    if (user_id) payload.user_id = user_id;
                } catch { }
            }

            const res = await request.post('/api/template/getMobileTemplatesRoute', payload);
            if (res?.data?.success === true) {
                const data = Array.isArray(res?.data?.data) ? res.data.data : [];
                if (data.length === 0) {
                    if (mode === 'replace') {
                        noMoreRef.current = false; // 查询为空但非分页尽头，允许后续条件变化再次查
                        setFetchedItems([]);
                        setTopIndex(0);
                    } else {
                        noMoreRef.current = true;
                    }
                    return [] as any[];
                }
                const dataWithPage = data.map((it: any) => ({ ...it, __pageNo: targetPage }));
                if (mode === 'append') {
                    setFetchedItems((prev) => (Array.isArray(prev) ? prev.concat(dataWithPage) : dataWithPage));
                } else {
                    setFetchedItems(dataWithPage);
                    setTopIndex(0);
                }
                setPage(targetPage);
                noMoreRef.current = false;
                return dataWithPage;
            }
            return null;
        } catch {
            return null;
        } finally {
            loadingRef.current = false;
            requestQueueRef.current.delete(requestKey);
            setIsLoading(false);
        }
    }, [filters, locale]);

    useEffect(() => {
        const currentSig = JSON.stringify(filters || {});
        if (lastFiltersSigRef.current === null) {
            lastFiltersSigRef.current = currentSig;
            return; // 首次 mount 已在上方初始化
        }
        if (lastFiltersSigRef.current === currentSig) return; // 过滤条件未变
        // 过滤条件改变：重置并拉取第一页
        lastFiltersSigRef.current = currentSig;
        noMoreRef.current = false;
        setPage(1);
        setTopIndex(0);
        setFetchedItems([]);
        fetchAndAppendPage(1, 'replace');
    }, [filters, fetchAndAppendPage]);

    // 当卡片索引改变时，重置拖拽状态
    useEffect(() => {
        setDeltaX(0);
        setIsDragging(false);
        // 向上传递可选的索引/卡片变化（父组件可忽略）
        try { /* onIndexChange && onIndexChange(topIndex); */ } catch (e) { }
        try { /* const currentCard = getCurrentCard(topIndex); onCurrentCardChange && onCurrentCardChange(currentCard, topIndex); */ } catch (e) { }
    }, [topIndex]); // 移除不稳定的依赖项，避免无限循环

    // 首次进入提示：中心 80% 区域可滑动，边缘不建议操作
    useEffect(() => {
        try {
            const shown = localStorage.getItem('CardsSwipeGuideShown');
            if (!shown) {
                setShowGuide(true);
                localStorage.setItem('CardsSwipeGuideShown', '1');
            }
        } catch (err) {
            // 若 localStorage 不可用，则本次会展示
            setShowGuide(true);
        }
    }, []);

    // 图片加载完成回调：记录已加载的图片，隐藏骨架屏
    const handleImageLoad = (id: number) => {
        setLoadedIds((prev) => {
            const next = new Set(prev);
            next.add(id);
            return next;
        });
    };

    // 图片加载失败回调：也标记为已加载，避免一直显示骨架屏
    const handleImageError = (id: number) => {
        setLoadedIds((prev) => {
            const next = new Set(prev);
            next.add(id);
            return next;
        });
    };

    // 首屏兜底：若 4 秒仍未 onLoad，结束骨架，避免长时间不可见
    useEffect(() => {
        const timers: number[] = [];
        const topCard = getCurrentCard(topIndex);
        if (topCard && !loadedIds.has(topCard.id)) {
            const id = window.setTimeout(() => {
                setLoadedIds((prev) => {
                    const next = new Set(prev);
                    next.add(topCard.id);
                    return next;
                });
            }, 4000);
            timers.push(id);
        }
        return () => { 
            timers.forEach((t) => window.clearTimeout(t)); 
        };
    }, [topIndex, loadedIds, getCurrentCard]); // 添加getCurrentCard依赖项，但使用useCallback优化

    // 立即显示缓存图：如果图片已在缓存（complete 且 naturalWidth>0），无须等待 onLoad
    useEffect(() => {
        const windowSizeValue = Number.isFinite(windowSize as number) ? (windowSize as number) : 4;
        const list = Array.from({ length: Math.min(windowSizeValue, cards.length - topIndex) }, (_, idx) => {
            const card = getCurrentCard(topIndex + idx);
            return card;
        }).filter(Boolean) as CardItem[];

        list.forEach((c) => {
            const el = imgRefs.current[c.id];
            try {
                if (el && el.complete && el.naturalWidth > 0) {
                    setLoadedIds((prev) => {
                        if (prev.has(c.id)) return prev;
                        const next = new Set(prev);
                        next.add(c.id);
                        return next;
                    });
                }
            } catch (error) {
                console.warn('检查图片缓存状态失败:', error);
            }
        });
    }, [cards, topIndex, windowSize, getCurrentCard]); // 添加getCurrentCard依赖项

    // 通知全局滚动状态变化
    const notifyScrollState = useCallback((shouldDisableScroll: boolean) => {
        try {
            // 发送自定义事件通知root-layout
            const event = new CustomEvent('cards_swipe_state_change', {
                detail: { disableScroll: shouldDisableScroll }
            });
            window.dispatchEvent(event);
        } catch (error) {
            console.warn('通知滚动状态变化失败:', error);
        }
    }, []);

    // 监听滑动激活状态变化，通知全局
    useEffect(() => {
        notifyScrollState(isSwipeActive);
        
        // 清理函数：组件卸载时重置滚动状态
        return () => {
            if (isSwipeActive) {
                notifyScrollState(false);
            }
        };
    }, [isSwipeActive, notifyScrollState]);

    // 撤回（回到上一条）
    const handleUndo = () => {
        // 如果正在动画或已到第一条，则不执行撤回
        if (isAnimating || topIndex <= 0) return;
        try {
            if (navigator.vibrate) navigator.vibrate(30);
        } catch (e) {
            // ignore
        }
        setTopIndex((v) => v - 1);
    };

    // 底部控制点击：仅处理滑动动画和卡片切换，不处理按钮逻辑
    const handleSwipeAction = useCallback((direction: "left" | "right", isButtonClick?: boolean) => {
        if (topIndex >= cards.length || isAnimating) return;
        // 为按钮点击提供不同的震动反馈
        try {
            if (direction === "right" && navigator.vibrate) {
                navigator.vibrate(isButtonClick ? 50 : 30); // 按钮点击震动更强
            } else if (direction === "left" && navigator.vibrate) {
                navigator.vibrate(isButtonClick ? 30 : 20); // 滑动震动较轻
            }
        } catch (e) {
            // ignore
        }
        setAnimateDirection(direction);
        setIsAnimating(true);
        // 触发全局进度为 1 来让第二张卡出现放大效果
        setDeltaX(direction === "right" ? threshold : -threshold);
        const SWIPE_ANIM_MS = 280; // 稍微缩短动画时间，提高响应性
        window.setTimeout(() => {
            // 立即更新索引，确保第二张卡片立即成为顶部卡片
            setTopIndex((v) => v + 1);
            // 立即重置所有动画状态，确保第二张卡片立即获得scale(1)
            setIsAnimating(false);
            setAnimateDirection(null);
            setDeltaX(0);
        }, SWIPE_ANIM_MS);
    }, [topIndex, cards.length, isAnimating, threshold]);

    // 独立的不喜欢按钮处理器：处理业务逻辑并触发卡片滑动
    const handleDislikeClick = useCallback(() => {
        if (topIndex >= cards.length || isAnimating) return;
        
        // 设置按钮选中状态，提供视觉反馈
        setButtonLeftSelected(true);
        const resetButtonTimer = setTimeout(() => setButtonLeftSelected(false), 200); // 200ms后恢复

        // 游客交互限制
        if (!isLoggedIn()) {
            if (getGuestActionCount() >= MAX_GUEST_ACTIONS) {
                try { 
                    openLoginModal(); 
                } catch (error) {
                    console.warn('打开登录弹窗失败:', error);
                }
                clearTimeout(resetButtonTimer); // 清理定时器
                setButtonLeftSelected(false);
                return;
            }
            try {
                const currentDisplayCard = getCurrentCard(topIndex);
                commitGuestAction("left", currentDisplayCard?.id);
            } catch (error) {
                console.warn('提交游客操作失败:', error);
            }
        }
        
        // 震动反馈
        try {
            if (navigator.vibrate) navigator.vibrate(50);
        } catch (error) {
            console.warn('震动反馈失败:', error);
        }
        
        // 触发卡片向左滑动动画
        handleSwipeAction("left", true); // 第二个参数标识为按钮点击
    }, [topIndex, cards.length, isAnimating, isLoggedIn, getGuestActionCount, getCurrentCard, handleSwipeAction]);

    // 独立的喜欢按钮处理器：处理业务逻辑并触发卡片滑动
    const handleLikeClick = useCallback(() => {
        if (topIndex >= cards.length || isAnimating) return;
        
        // 设置按钮选中状态，提供视觉反馈
        setButtonRightSelected(true);
        const resetButtonTimer = setTimeout(() => setButtonRightSelected(false), 200); // 200ms后恢复
        
        // 游客交互限制
        if (!isLoggedIn()) {
            if (getGuestActionCount() >= MAX_GUEST_ACTIONS) {
                try { 
                    openLoginModal(); 
                } catch (error) {
                    console.warn('打开登录弹窗失败:', error);
                }
                clearTimeout(resetButtonTimer); // 清理定时器
                setButtonRightSelected(false);
                return;
            }
            try {
                const currentDisplayCard = getCurrentCard(topIndex);
                commitGuestAction("right", currentDisplayCard?.id);
            } catch (error) {
                console.warn('提交游客操作失败:', error);
            }
        }

        // 已登录用户的点赞逻辑
        if (isLoggedIn()) {
            const currentDisplayCard = getCurrentCard(topIndex);
            const tplId = (typeof currentDisplayCard?.raw?.id === 'number') ? currentDisplayCard?.raw?.id : currentDisplayCard?.id;
            likeTemplate(tplId);
        }
        // 震动反馈
        try {
            if (navigator.vibrate) navigator.vibrate(50);
        } catch (error) {
            // ignore
        }
        // 触发卡片向右滑动动画
        handleSwipeAction("right", true); // 第二个参数标识为按钮点击
    }, [topIndex, cards.length, isAnimating, isLoggedIn, getCurrentCard, likeTemplate, handleSwipeAction]);

    // 预测性预加载：基于滑动速度和方向预测用户行为
    const lastTouchTimeRef = useRef(0);
    const lastTouchXRef = useRef(0);

    // 优化的触摸开始事件处理
    const handleTouchStart = useCallback((e: React.TouchEvent) => {
        if (isAnimating || topIndex >= cards.length) return;
        
        const touch = e.touches[0];
        setTouchStartX(touch.clientX);
        setTouchStartY(touch.clientY);
        setIsDragging(true);
        setDeltaX(0);
        setDeltaY(0);
        setIsSwipeActive(false); // 初始状态不激活滑动

        // 记录触摸开始时间和位置，用于计算滑动速度
        lastTouchTimeRef.current = Date.now();
        lastTouchXRef.current = touch.clientX;
        lastPositionRef.current = touch.clientX;
        velocityRef.current = 0;
        
        // 取消之前的动画帧
        if (animationFrameRef.current) {
            cancelAnimationFrame(animationFrameRef.current);
            animationFrameRef.current = null;
        }
    }, [isAnimating, topIndex, cards.length]);

    // 优化的触摸移动事件处理
    const handleTouchMove = useCallback((e: React.TouchEvent) => {
        if (!isDragging || isAnimating) return;
        
        const touch = e.touches[0];
        const deltaX = touch.clientX - touchStartX;
        const deltaY = touch.clientY - touchStartY;
        
        // 更精确的手势判断
        const absDeltaX = Math.abs(deltaX);
        const absDeltaY = Math.abs(deltaY);
        const horizontalThreshold = 10; // 水平滑动最小距离
        const verticalRatio = 2.0; // 提高垂直滑动容忍度
        
        // 计算滑动速度
        const currentTime = Date.now();
        const timeDelta = currentTime - lastTouchTimeRef.current;
        
        if (timeDelta > 8) { // 限制更新频率到120fps，提高响应性
            const positionDelta = touch.clientX - lastPositionRef.current;
            velocityRef.current = positionDelta / timeDelta; // px/ms
            lastTouchTimeRef.current = currentTime;
            lastPositionRef.current = touch.clientX;
        }
        
        // 判断是否应该激活滑动模式
        if (absDeltaX >= horizontalThreshold && absDeltaY < absDeltaX * verticalRatio) {
            if (!isSwipeActive) {
                setIsSwipeActive(true); // 激活滑动模式，禁用页面滚动
                // 阻止默认的滚动行为
                e.preventDefault();
            }
            
            // 限制滑动距离，提供更好的手感
            const maxDelta = threshold * 2.5;
            const clampedDeltaX = Math.max(-maxDelta, Math.min(maxDelta, deltaX));
            
            // 使用requestAnimationFrame优化性能
            if (animationFrameRef.current) {
                cancelAnimationFrame(animationFrameRef.current);
            }
            
            animationFrameRef.current = requestAnimationFrame(() => {
                setDeltaX(clampedDeltaX);
                setDeltaY(deltaY);
                lastUpdateTimeRef.current = currentTime;
            });
        } else if (absDeltaY > absDeltaX && !isSwipeActive) {
            // 垂直滑动占主导且未激活滑动模式，允许页面滚动
            return;
        }
        
        // 如果已经激活滑动模式，阻止默认行为
        if (isSwipeActive) {
            e.preventDefault();
        }
    }, [isDragging, isAnimating, touchStartX, touchStartY, threshold, isSwipeActive]);

    // 优化的触摸结束事件处理
    const handleTouchEnd = useCallback((e: React.TouchEvent) => {
        if (!isDragging) return;
        
        setIsDragging(false);
        setIsSwipeActive(false); // 结束滑动，恢复页面滚动
        
        // 取消动画帧
        if (animationFrameRef.current) {
            cancelAnimationFrame(animationFrameRef.current);
            animationFrameRef.current = null;
        }
        
        const absDeltaX = Math.abs(deltaX);
        const velocity = Math.abs(velocityRef.current); 
        
        // 结合滑动距离和速度判断是否切换卡片
        const velocityThreshold = 0.3; // px/ms
        const shouldSwipe = absDeltaX > threshold || (absDeltaX > threshold * 0.4 && velocity > velocityThreshold);
         
        if (shouldSwipe) {
            const direction = deltaX > 0 ? "right" : "left";
            
            // 修复：滑动手势也应该执行业务逻辑，保持与按钮点击的一致性
            if (direction === "left") {
                // 不喜欢的业务逻辑
                if (!isLoggedIn()) {
                    if (getGuestActionCount() >= MAX_GUEST_ACTIONS) {
                        try { 
                            openLoginModal(); 
                        } catch (error) {
                            console.warn('打开登录弹窗失败:', error);
                        }
                        // 重置滑动状态
                        setDeltaX(0);
                        setDeltaY(0);
                        return;
                    }
                    try {
                        const currentDisplayCard = getCurrentCard(topIndex);
                        commitGuestAction("left", currentDisplayCard?.id);
                    } catch (error) {
                        console.warn('提交游客操作失败:', error);
                    }
                }
            } else if (direction === "right") {
                // 喜欢的业务逻辑
                if (!isLoggedIn()) {
                    if (getGuestActionCount() >= MAX_GUEST_ACTIONS) {
                        try { 
                            openLoginModal(); 
                        } catch (error) {
                            console.warn('打开登录弹窗失败:', error);
                        }
                        // 重置滑动状态
                        setDeltaX(0);
                        setDeltaY(0);
                        return;
                    }
                    try {
                        const currentDisplayCard = getCurrentCard(topIndex);
                        commitGuestAction("right", currentDisplayCard?.id);
                    } catch (error) {
                        console.warn('提交游客操作失败:', error);
                    }
                }
                
                // 已登录用户的点赞逻辑
                if (isLoggedIn()) {
                    try {
                        const currentDisplayCard = getCurrentCard(topIndex);
                        if (currentDisplayCard && !isAlreadyLiked(currentDisplayCard.id)) {
                            // 这里应该调用点赞API
                            console.log('点赞卡片:', currentDisplayCard.id);
                        }
                    } catch (error) {
                        console.warn('点赞操作失败:', error);
                    }
                }
            }
            
            // 震动反馈
            try {
                if (navigator.vibrate) navigator.vibrate(50);
            } catch (error) {
                console.warn('震动反馈失败:', error);
            }
            
            // 触发卡片切换动画
            handleSwipeAction(direction);
        } else {
            // 滑动距离不足，重置位置
            setDeltaX(0);
            setDeltaY(0);
        }
    }, [isDragging, deltaX, threshold, isLoggedIn, getGuestActionCount, getCurrentCard, topIndex, isAlreadyLiked, handleSwipeAction]);

    // 清理函数
    useEffect(() => {
        return () => {
            if (animationFrameRef.current) {
                cancelAnimationFrame(animationFrameRef.current);
            }
        };
    }, []);

    // 优化的预加载触发机制：内部自行请求下一页
    useEffect(() => {
        if (skipFirstPrefetchAfterRestoreRef.current) {
            // 恢复后抑制一次自动预取，避免回到页面立即触发加载
            skipFirstPrefetchAfterRestoreRef.current = false;
            return;
        }
        const remaining = cards.length - topIndex;
        const thresholdToUse = Math.max(1, Number.isFinite(prefetchThreshold as number) ? (prefetchThreshold as number) : 6);
        const debounceDelay = 800;
        const timeoutId = setTimeout(() => {
            if (remaining <= thresholdToUse && !loadingRef.current && !noMoreRef.current) {
                fetchAndAppendPage(page + 1, 'append');
            }
        }, debounceDelay);
        return () => clearTimeout(timeoutId);
    }, [cards.length, topIndex, prefetchThreshold, fetchAndAppendPage, page]);

    // 状态持久化：索引、数据或分页变化时保存
    const saveStateToStorage = useCallback(() => {
        try {
            const payload = {
                items: fetchedItems,
                page,
                topIndex,
                noMore: !!noMoreRef.current,
                filtersSignature: JSON.stringify(filters || {}),
                path: typeof window !== 'undefined' ? window.location.pathname : '',
                timestamp: Date.now(),
            };
            sessionStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
        } catch { }
    }, [fetchedItems, page, topIndex, filters]);

    useEffect(() => { saveStateToStorage(); }, [saveStateToStorage]);

    // 页面隐藏/卸载时也保存
    useEffect(() => {
        const handleBeforeUnload = () => { saveStateToStorage(); };
        const handleVisibilityChange = () => {
            try { if (document.visibilityState === 'hidden') saveStateToStorage(); } catch { }
        };
        window.addEventListener('beforeunload', handleBeforeUnload);
        document.addEventListener('visibilitychange', handleVisibilityChange);
        return () => {
            window.removeEventListener('beforeunload', handleBeforeUnload);
            document.removeEventListener('visibilitychange', handleVisibilityChange);
        };
    }, [saveStateToStorage]);

    // 优化加载状态显示逻辑，避免白屏问题（内部加载）
    if (isLoading && cards.length === 0) {
        // 完全没有数据时显示骨架屏
        return (
            <div className={containerClass}>
                {/* 渲染最后一张卡片的样式，保持完全一致的布局 */}
                <div
                    className="absolute inset-0 w-full h-full"
                    style={{
                        transform: "translateY(0px) scale(1)",
                        zIndex: 5,
                        pointerEvents: "auto",
                        willChange: "transform",
                        transition: "none"
                    }}
                    onTouchStart={handleTouchStart}
                    onTouchMove={handleTouchMove}
                    onTouchEnd={handleTouchEnd}
                // onClick={() => onCardClick && onCardClick(lastCard)}
                >
                    <div className="w-full h-[89.5%] rounded-2xl overflow-hidden shadow-lg relative bg-white dark:bg-gray-800">
                        {/* 类骨架屏加载样式 - 与正常卡片加载时完全一致 */}
                        <div className="absolute inset-0 flex items-center justify-center bg-gray-200" style={{ opacity: 1 }}>
                            <span className="absolute animate-spin">
                                <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19775" width="40" height="40"><path d="M512 1024c-19.2 0-35.2-16-35.2-35.2s16-35.2 35.2-35.2c246.4 0 444.8-198.4 444.8-444.8S758.4 67.2 512 67.2 67.2 264 67.2 512c0 108.8 38.4 211.2 108.8 291.2 12.8 16 9.6 35.2-3.2 48-16 12.8-35.2 9.6-48-3.2-38.4-44.8-70.4-96-92.8-150.4C9.6 640 0 576 0 513.6c0-70.4 12.8-134.4 41.6-198.4 25.6-60.8 60.8-115.2 108.8-163.2s102.4-83.2 163.2-108.8C377.6 14.4 444.8 1.6 512 1.6s134.4 12.8 198.4 41.6c60.8 25.6 115.2 60.8 163.2 108.8s83.2 102.4 108.8 163.2c28.8 64 41.6 131.2 41.6 198.4s-12.8 134.4-41.6 198.4c-25.6 60.8-60.8 115.2-108.8 163.2s-102.4 83.2-163.2 108.8c-64 25.6-128 40-198.4 40z" fill="#d4237a" p-id="19776"></path></svg>
                            </span>
                        </div>
                    </div>
                </div>

                {/* 底部操作区：保证最上层并根据滑动方向展示选中样式 */}
                <div className="absolute -mb-[2.8rem] flex justify-between w-[80%] mr-[10%] right-0 p-2"
                    style={{ zIndex: 150, pointerEvents: "auto", bottom: `calc(env(safe-area-inset-bottom) + 4rem)` }}>
                    {/* 不喜欢按钮 - 独立处理，不触发滑动 */}
                    <button onClick={handleDislikeClick} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: buttonLeftSelected ? "#D9D9D9" : "#FFFFFF" }}>
                        <img src={buttonLeftSelected ? select_dislikeIcon : dislikeIcon} alt="dislike" className="w-[60%] object-contain m-auto mt-1" />
                    </button>
                    {/* 撤回按钮 */}
                    <button onClick={handleUndo} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: "#FFFFFF" }}>
                        <img src={backIcon} alt="undo" className="w-[60%] object-contain m-auto mt-1" />
                    </button>
                    {/* 喜欢按钮 - 独立处理，不触发滑动 */}
                    <button onClick={handleLikeClick} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: buttonRightSelected ? "#FF87BB" : "#FFFFFF" }}>
                        <img src={buttonRightSelected ? select_likeIcon : likeIcon} alt="like" className="w-[60%] object-contain m-auto mt-1" />
                    </button>
                </div>
            </div>
        );
    }

    if (!isLoading && cards.length === 0) {
        return (
            <div className={containerClass}>
                {/* {t('home.not_found')} */}
                <div className="text-gray-500 dark:text-gray-300 text-center mt-10">Get the first data card on the homepage:{cards.length}</div>
            </div>
        );
    }

    if (cards.length > 0 && topIndex >= cards.length) {
        // 当所有卡片都已浏览完毕时，显示类骨架屏加载样式，保持与正常卡片完全一致的布局
        const lastCard = cards[cards.length - 1];
        return (
            <div className={containerClass}>
                {/* 渲染最后一张卡片的样式，保持完全一致的布局 */}
                <div
                    className="absolute inset-0 w-full h-full"
                    style={{
                        transform: "translateY(0px) scale(1)",
                        zIndex: 5,
                        pointerEvents: "auto",
                        willChange: "transform",
                        transition: "none"
                    }}
                    onTouchStart={handleTouchStart}
                    onTouchMove={handleTouchMove}
                    onTouchEnd={handleTouchEnd}
                    onClick={() => onCardClick && onCardClick(lastCard)}
                >
                    <div className="w-full h-[89.5%] rounded-2xl overflow-hidden shadow-lg relative bg-white dark:bg-gray-800">
                        {/* 背景卡片内容 - 降低透明度作为背景 */}
                        {lastCard?.src && (
                            <img
                                ref={(el) => { if (el) imgRefs.current[lastCard.id] = el; }}
                                src={lastCard.src}
                                alt={lastCard.title || "Card"}
                                className="w-full h-full object-cover"
                                onLoad={() => handleImageLoad(lastCard.id)}
                                onError={() => handleImageError(lastCard.id)}
                                style={{ opacity: 0.3 }} // 降低透明度作为背景
                            />
                        )}

                        {/* 类骨架屏加载样式 - 与正常卡片加载时完全一致 */}
                        <div className="absolute inset-0 flex items-center justify-center bg-gray-200" style={{ opacity: 1 }}>
                            {/* loading 动画 */}
                            <span className="absolute animate-spin">
                                <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19775" width="40" height="40"><path d="M512 1024c-19.2 0-35.2-16-35.2-35.2s16-35.2 35.2-35.2c246.4 0 444.8-198.4 444.8-444.8S758.4 67.2 512 67.2 67.2 264 67.2 512c0 108.8 38.4 211.2 108.8 291.2 12.8 16 9.6 35.2-3.2 48-16 12.8-35.2 9.6-48-3.2-38.4-44.8-70.4-96-92.8-150.4C9.6 640 0 576 0 513.6c0-70.4 12.8-134.4 41.6-198.4 25.6-60.8 60.8-115.2 108.8-163.2s102.4-83.2 163.2-108.8C377.6 14.4 444.8 1.6 512 1.6s134.4 12.8 198.4 41.6c60.8 25.6 115.2 60.8 163.2 108.8s83.2 102.4 108.8 163.2c28.8 64 41.6 131.2 41.6 198.4s-12.8 134.4-41.6 198.4c-25.6 60.8-60.8 115.2-108.8 163.2s-102.4 83.2-163.2 108.8c-64 25.6-128 40-198.4 40z" fill="#d4237a" p-id="19776"></path></svg>
                            </span>
                        </div>

                        {/* 文本覆盖层 - 与正常卡片完全一致的布局 */}
                        <div className="absolute w-full inset-0 pointer-events-none flex flex-col justify-end">
                            <div className="p-4 pb-12 rounded-md w-full text-white pointer-events-auto" style={{
                                background: 'linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.6) 40%, rgba(0,0,0,0) 100%)'
                            }}>
                                <p style={{ fontWeight: "bold", opacity: 0.5 }} className="text-2xl font-semibold">{lastCard?.title}</p>
                                <p className="text-[1rem] text-gray-100 mt-1" style={{ opacity: 0.5 }}>{lastCard?.desc}</p>
                            </div>
                        </div>
                    </div>
                </div>

                {/* 底部操作区：保证最上层并根据滑动方向展示选中样式 */}
                <div className="absolute -mb-[2.8rem] flex justify-between w-[80%] mr-[10%] right-0 p-2"
                    style={{ zIndex: 150, pointerEvents: "auto", bottom: `calc(env(safe-area-inset-bottom) + 4rem)` }}>
                    {/* 不喜欢按钮 - 独立处理，不触发滑动 */}
                    <button onClick={handleDislikeClick} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: buttonLeftSelected ? "#D9D9D9" : "#FFFFFF" }}>
                        <img src={buttonLeftSelected ? select_dislikeIcon : dislikeIcon} alt="dislike" className="w-[60%] object-contain m-auto mt-1" />
                    </button>
                    {/* 撤回按钮 */}
                    <button onClick={handleUndo} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: "#FFFFFF" }}>
                        <img src={backIcon} alt="undo" className="w-[60%] object-contain m-auto mt-1" />
                    </button>
                    {/* 喜欢按钮 - 独立处理，不触发滑动 */}
                    <button onClick={handleLikeClick} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: buttonRightSelected ? "#FF87BB" : "#FFFFFF" }}>
                        <img src={buttonRightSelected ? select_likeIcon : likeIcon} alt="like" className="w-[60%] object-contain m-auto mt-1" />
                    </button>
                </div>
            </div>
        );
    }

    return (
        <div className={containerClass}>
            {/* 卡片堆（窗口化渲染，仅渲染顶部若干张以降低 DOM 体量） */}
            {Array.from({ length: Math.min(Number.isFinite(windowSize as number) ? (windowSize as number) : 4, cards.length - topIndex) }, (_, idx) => {
                const card = getCurrentCard(topIndex + idx);
                if (!card) return null;
                return { card, idx };
            }).filter((item): item is { card: CardItem; idx: number } => item !== null && item !== undefined).map(({ card, idx }) => {
                const isTop = idx === 0;
                const absoluteIndex = topIndex + idx; // 计算绝对索引
                const offset = 0; // 所有卡片都在相同的垂直位置，通过zIndex和scale区分层次
                // 性能优化：使用 useMemo 缓存计算结果
                const cardTransforms = useMemo(() => {
                    const transforms: { [key: number]: string } = {};
                    const windowSizeNum = Number.isFinite(windowSize as number) ? (windowSize as number) : 4;
                    const visibleCount = Math.min(windowSizeNum, cards.length - topIndex);
                    
                    for (let idx = 0; idx < visibleCount; idx++) {
                        const isTop = idx === 0;
                        const isExiting = isTop && isAnimating && animateDirection !== null;
                        
                        if (isTop) {
                            const exitX = isExiting
                                ? (animateDirection === "right" ? window.innerWidth * 1.2 : -window.innerWidth * 1.2)
                                : 0;
                            const exitRotate = isExiting ? (animateDirection === "right" ? 20 : -20) : 0;
                            const dragX = isDragging ? deltaX : 0;
                            const dragRotate = isDragging ? (deltaX / threshold) * 12 : 0;
                            
                            transforms[idx] = isExiting
                                ? `translate3d(${exitX}px, 0, 0) rotate(${exitRotate}deg) scale(1)`
                                : `translate3d(${dragX}px, 0, 0) rotate(${dragRotate}deg) scale(1)`;
                        } else {
                            const cardScale = 1 - idx * 0.1;
                            if (idx === 1 && (isDragging || isAnimating)) {
                                const scaleProgress = Math.abs(globalProgress);
                                const dynamicScale = Math.min(1.0, cardScale + scaleProgress * 0.1);
                                transforms[idx] = `translate3d(0, 0, 0) scale(${dynamicScale})`;
                            } else {
                                transforms[idx] = `translate3d(0, 0, 0) scale(${cardScale})`;
                            }
                        }
                    }
                    return transforms;
                }, [topIndex, cards.length, windowSize, isAnimating, animateDirection, isDragging, deltaX, threshold, globalProgress]);
                
                // 性能优化：使用 useMemo 缓存卡片样式
                const getCardStyle = useCallback((idx: number, isTop: boolean): React.CSSProperties => {
                    const isExiting = isTop && isAnimating && animateDirection !== null;
                    
                    return {
                        transform: cardTransforms[idx] || 'translate3d(0, 0, 0) scale(1)',
                        zIndex: 5 - idx,
                        pointerEvents: isTop ? "auto" : "none",
                        willChange: isTop ? "transform" : "auto",
                        transition: isExiting
                            ? "transform 0.28s cubic-bezier(0.25, 0.46, 0.45, 0.94)"
                            : (isDragging
                                ? "none"
                                : (isAnimating
                                    ? "none"
                                    : "transform 0.2s cubic-bezier(0.4, 0.0, 0.2, 1)"
                                )
                            ),
                        height: 'calc(100% - 4rem)',
                        backfaceVisibility: 'hidden' as const,
                        perspective: 1000,
                        // 添加 contain 属性优化渲染性能
                        contain: 'layout style paint',
                        // 使用 transform3d 强制开启硬件加速
                        WebkitTransform: cardTransforms[idx] || 'translate3d(0, 0, 0) scale(1)',
                        // iOS Safari 兼容性优化
                        WebkitBackfaceVisibility: 'hidden',
                        WebkitPerspective: 1000,
                        // Android Chrome 兼容性优化
                        transformStyle: 'preserve-3d' as const,
                        // 防止iOS Safari的橡皮筋效果
                        WebkitOverflowScrolling: 'touch',
                        // 优化触摸响应
                        WebkitTouchCallout: 'none',
                        WebkitUserSelect: 'none',
                        userSelect: 'none',
                    };
                }, [cardTransforms, isAnimating, animateDirection, isDragging]);
                
                // 性能优化：防抖处理触摸移动事件
                const throttledTouchMove = useCallback(
                    throttle((e: React.TouchEvent<HTMLDivElement>) => {
                        if (!isDragging || !touchStartX || !touchStartY) return;
                    
                        const touch = e.touches[0];
                        const currentDeltaX = touch.clientX - touchStartX;
                        const currentDeltaY = touch.clientY - touchStartY;
                    
                        // 使用 RAF 优化性能
                        if (animationFrameRef.current) {
                            cancelAnimationFrame(animationFrameRef.current);
                        }
                    
                        animationFrameRef.current = requestAnimationFrame(() => {
                            const now = performance.now();
                            const timeDelta = now - (lastUpdateTimeRef.current || now);
                            
                            if (timeDelta >= 16) { // 限制为 60fps
                                setDeltaX(currentDeltaX);
                                setDeltaY(currentDeltaY);
                                
                                // 计算速度
                                const distance = Math.abs(currentDeltaX - (lastPositionRef.current || 0));
                                velocityRef.current = distance / Math.max(timeDelta, 1);
                                lastPositionRef.current = currentDeltaX;
                                lastUpdateTimeRef.current = now;
                            }
                        });
                    
                        // 判断是否应该激活滑动状态
                        const shouldActivateSwipe = Math.abs(currentDeltaX) > Math.abs(currentDeltaY) && Math.abs(currentDeltaX) > 10;
                        if (shouldActivateSwipe && !isSwipeActive) {
                            setIsSwipeActive(true);
                            e.preventDefault();
                        }
                    }, 16), // 16ms 约等于 60fps
                    [isDragging, touchStartX, touchStartY, isSwipeActive]
                );

                const style = getCardStyle(idx, isTop);

                const handleCardClick = () => {
                    console.log("card clicked:", card);
                    onCardClick?.(card);
                };

                return (
                    <React.Fragment key={`card-${absoluteIndex}`}>
                        {/* 单张卡片  */}
                        <div
                            key={`card-${absoluteIndex}`}
                            className="absolute w-full h-full rounded-2xl overflow-hidden shadow-lg touch-none select-none"
                            style={{
                                ...style,
                                // touchAction 在下面已使用更完整的 'pan-y manipulation'，此处移除重复项
                                // 移动端兼容性优化
                                WebkitTapHighlightColor: 'transparent',
                                WebkitTouchCallout: 'none',
                                WebkitUserSelect: 'none',
                                MozUserSelect: 'none',
                                msUserSelect: 'none',
                                userSelect: 'none',
                                // 防止iOS Safari的双击缩放
                                touchAction: isTop ? 'pan-y manipulation' : 'auto',
                                // 优化Android Chrome的滚动性能
                                overscrollBehavior: 'contain',
                            }}
                            onTouchStart={isTop ? handleTouchStart : undefined}
                            onTouchMove={isTop ? throttledTouchMove : undefined}
                            onTouchEnd={isTop ? handleTouchEnd : undefined}
                            onClick={handleCardClick}
                        >
                            {/* 图片 + 骨架屏 */}
                            <img
                                ref={(el) => { imgRefs.current[card.id] = el; }}
                                src={card.src || ''}
                                alt={card.title}
                                className="w-full h-full object-cover object-top block"
                                style={{
                                    width: "100%",
                                    height: "100%",
                                    transition: 'opacity 0.3s ease-in-out',
                                    // 优化图片渲染性能
                                    imageRendering: 'auto',
                                    WebkitBackfaceVisibility: 'hidden',
                                    backfaceVisibility: 'hidden',
                                }}
                                draggable={false}
                                loading={idx <= 1 ? 'eager' : 'lazy'}
                                decoding={idx === 0 ? 'sync' as any : 'async'}
                                sizes="(max-width: 640px) 100vw, 50vw"
                                onLoad={() => handleImageLoad(card.id)}
                                onError={() => handleImageError(card.id)}
                            />

                            {/* 数据加载或者渲染的时候展示loading动画 */}
                            {!loadedIds.has(card.id) && (
                                <div className="absolute inset-0 flex items-center justify-center bg-gray-200 " style={{ opacity: 1, }}>
                                    <span className="absolute animate-spin">
                                        <svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="19775" width="40" height="40"><path d="M512 1024c-19.2 0-35.2-16-35.2-35.2s16-35.2 35.2-35.2c246.4 0 444.8-198.4 444.8-444.8S758.4 67.2 512 67.2 67.2 264 67.2 512c0 108.8 38.4 211.2 108.8 291.2 12.8 16 9.6 35.2-3.2 48-16 12.8-35.2 9.6-48-3.2-38.4-44.8-70.4-96-92.8-150.4C9.6 640 0 576 0 513.6c0-70.4 12.8-134.4 41.6-198.4 25.6-60.8 60.8-115.2 108.8-163.2s102.4-83.2 163.2-108.8C377.6 14.4 444.8 1.6 512 1.6s134.4 12.8 198.4 41.6c60.8 25.6 115.2 60.8 163.2 108.8s83.2 102.4 108.8 163.2c28.8 64 41.6 131.2 41.6 198.4s-12.8 134.4-41.6 198.4c-25.6 60.8-60.8 115.2-108.8 163.2s-102.4 83.2-163.2 108.8c-64 25.6-128 40-198.4 40z" fill="#d4237a" p-id="19776"></path></svg>
                                    </span>
                                </div>
                            )}
                            {/* 文本覆盖：加大高度、增加底部间距并加深蒙版 */}
                            <div className="absolute w-full  inset-0 pointer-events-none flex flex-col justify-end">
                                <div className="p-4 pb-12 rounded-md w-full text-white pointer-events-auto" style={{
                                    background: 'linear-gradient(to top, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.6) 40%, rgba(0,0,0,0) 100%)'
                                }}>
                                    <p style={{ fontWeight: "bold" }} className="text-2xl font-semibold">{card.title}</p>
                                    <p className="text-[1rem] text-gray-100 mt-1">{card.desc}</p>
                                </div>
                            </div>
                        </div>
                    </React.Fragment>
                );
            })}

            {/* 首次进入用户引导层：提示可操作区域（中心 80%），点击任意处或按钮关闭 */}
            {showGuide && (
                <div className="absolute inset-0 flex items-center justify-center" style={{ zIndex: 1000, background: 'rgba(0,0,0,0.55)' }} onClick={() => setShowGuide(false)}>
                    <div className="relative w-[80%] h-[90%] flex items-center justify-center text-center text-white rounded-xl" style={{ border: '2px dashed rgba(255,255,255,0.9)', background: 'rgba(255,255,255,0.06)', backdropFilter: 'blur(1px)' }} onClick={(e) => e.stopPropagation()}>
                        <div className="px-4">
                            <div className="text-lg font-semibold mb-2">{t('cards.swipe_area_title')}</div>
                            <div className="text-sm opacity-90 mb-4">{t('cards.swipe_area_desc')}</div>
                            <button className="px-4 py-2 rounded-md bg-white text-gray-900 font-medium shadow" onClick={() => setShowGuide(false)}>
                                {t('cards.got_it')}
                            </button>
                        </div>
                        {/* 闪烁效果：环形微光与中心波纹，吸引用户注意 */}
                        <div className="pointer-events-none absolute inset-0 rounded-xl ring-2 ring-white/80 animate-pulse" />
                        <div className="pointer-events-none absolute w-4 h-4 rounded-full bg-white/90 animate-ping shadow" style={{ left: '50%', top: '50%', transform: 'translate(-50%, -50%)' }} />
                        {/* 四角装饰，强调操作区域 */}
                        <div className="pointer-events-none absolute inset-0">
                            <div className="absolute left-2 top-2 w-6 h-6 border-l-2 border-t-2 border-white/90 rounded-tl-md" />
                            <div className="absolute right-2 top-2 w-6 h-6 border-r-2 border-t-2 border-white/90 rounded-tr-md" />
                            <div className="absolute left-2 bottom-2 w-6 h-6 border-l-2 border-b-2 border-white/90 rounded-bl-md" />
                            <div className="absolute right-2 bottom-2 w-6 h-6 border-r-2 border-b-2 border-white/90 rounded-br-md" />
                        </div>
                    </div>
                </div>
            )}

            {/* 底部操作区：保证最上层并根据滑动方向展示选中样式 */}
            <div className="absolute -mb-[2.8rem] flex justify-between w-[80%] mr-[10%] right-0 p-2"
                style={{ zIndex: 150, pointerEvents: "auto", bottom: `calc(env(safe-area-inset-bottom) + 4rem)` }}>
                {/* 不喜欢按钮 - 独立处理，不触发滑动 */}
                <button onClick={handleDislikeClick} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: buttonLeftSelected ? "#D9D9D9" : "#FFFFFF" }}>
                    <img src={buttonLeftSelected ? select_dislikeIcon : dislikeIcon} alt="dislike" className="w-[60%] object-contain m-auto mt-1" />
                </button>
                {/* 撤回按钮 */}
                <button onClick={handleUndo} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: "#FFFFFF" }}>
                    <img src={backIcon} alt="undo" className="w-[60%] object-contain m-auto mt-1" />
                </button>
                {/* 喜欢按钮 - 独立处理，不触发滑动 */}
                <button onClick={handleLikeClick} className="w-16 h-16 shadow-sm shadow-gray-300 rounded-full" style={{ backgroundColor: buttonRightSelected ? "#FF87BB" : "#FFFFFF" }}>
                    <img src={buttonRightSelected ? select_likeIcon : likeIcon} alt="like" className="w-[60%] object-contain m-auto mt-1" />
                </button>
            </div>
        </div>
    );
});

export default Cards;



interface CardData {
  id: string;
  name: string;
  age: number;
  avatar: string;
  images: string[];
  bio?: string;
  distance?: number;
  interests?: string[];
  occupation?: string;
  education?: string;
  height?: number;
  location?: string;
  verified?: boolean;
  lastActive?: string;
  mutualFriends?: number;
  zodiacSign?: string;
  lifestyle?: {
    smoking?: string;
    drinking?: string;
    exercise?: string;
    pets?: string;
  };
  preferences?: {
    ageRange?: [number, number];
    distance?: number;
    interests?: string[];
  };
}

interface TouchEvent {
  touches: TouchList;
  changedTouches: TouchList;
  targetTouches: TouchList;
  preventDefault: () => void;
  stopPropagation: () => void;
}

interface SwipeDirection {
  x: number;
  y: number;
  distance: number;
  velocity: number;
  angle: number;
}


